package com.rs.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import com.rs.cache.Cache;
import com.rs.io.InputStream;
import com.rs.io.OutputStream;
import com.rs.utils.bzip2.BZip2Decompressor;
import com.rs.utils.gzip.GZipCompressor;
import com.rs.utils.gzip.GZipDecompressor;

public final class Utils {


	private static final Object ALGORITHM_LOCK = new Object();
	
	public static final byte[] encryptUsingMD5(byte[] buffer) {
		//prevents concurrency problems with the algorithm
		synchronized(ALGORITHM_LOCK) {
			try {
				MessageDigest algorithm = MessageDigest.getInstance("MD5");
				algorithm.update(buffer);
				byte[]  digest = algorithm.digest();
				algorithm.reset();
				return digest;
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			}
			return null;
		}
	}
	
	public static final int getDistance(int coordX1, int coordY1, int coordX2, int coordY2) {
		int deltaX = coordX2 - coordX1;
		int deltaY = coordY2 - coordY1;
		return ((int) Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)));
	}
	
	public static final byte[] DIRECTION_DELTA_X = new byte[] {-1, 0, 1, -1, 1, -1, 0, 1};
	public static final byte[] DIRECTION_DELTA_Y = new byte[] {1, 1, 1, 0, 0, -1, -1, -1};

	public static final int getFaceDirection(int xOffset, int yOffset) {
		if (xOffset < 0) {
			if (yOffset < 0)
				return 5;
			else if (yOffset > 0)
				return 0;
			else
				return 3;
		} else if (xOffset > 0) {
			if (yOffset < 0)
				return 7;
			else if (yOffset > 0)
				return 2;
			else
				return 4;
		} else {
			if (yOffset < 0)
				return 6;
			else if (yOffset > 0)
				return 1;
			else
				return -1;
		}
	}
	
	public static final int getObjectDefinitionsSize() {
		int lastContainerId = Cache.getCacheFileManagers()[16].getContainersSize()-1;
		return lastContainerId * 256 + Cache.getCacheFileManagers()[16].getFilesSize(lastContainerId);
	}
	
	public static final int getNPCDefinitionsSize() {
		int lastContainerId = Cache.getCacheFileManagers()[18].getContainersSize()-1;
		return lastContainerId * 128 + Cache.getCacheFileManagers()[18].getFilesSize(lastContainerId);
	}
	
	public static final int getItemDefinitionsSize() {
		int lastContainerId = Cache.getCacheFileManagers()[19].getContainersSize()-1;
		return lastContainerId * 256 + Cache.getCacheFileManagers()[19].getFilesSize(lastContainerId);
	}
	
	public static final int getInterfaceDefinitionsSize() {
		return Cache.getCacheFileManagers()[3].getContainersSize();
	}
	
	public static final int getInterfaceDefinitionsComponentsSize(int interfaceId) {
		return Cache.getCacheFileManagers()[3].getFilesSize(interfaceId);
	}
	
	public static String formatPlayerNameForProtocol(String name) {
		if(name == null)
			return "";
		name = name.replaceAll(" ", "_");
		name = name.toLowerCase();
		return name;
	}

	public static String formatPlayerNameForDisplay(String name) {
		if(name == null)
			return "";
		name = name.replaceAll("_", " ");
		name = name.toLowerCase();
		StringBuilder newName = new StringBuilder();
		boolean wasSpace = true;
		for (int i = 0; i < name.length(); i++) {
			if (wasSpace) {
				newName.append(("" + name.charAt(i)).toUpperCase());
				wasSpace = false;
			} else {
				newName.append(name.charAt(i));
			}
			if (name.charAt(i) == ' ') {
				wasSpace = true;
			}
		}
		return newName.toString();
	}
	
	public static final int getRandom(int maxValue) {
		return (int) (Math.random() * (maxValue + 1));
	}

	
	public static final String longToString(long l) {
		if (l <= 0L || l >= 0x5b5b57f8a98a5dd1L)
			return null;
		if (l % 37L == 0L)
			return null;
		int i = 0;
		char ac[] = new char[12];
		while (l != 0L) {
			long l1 = l;
			l /= 37L;
			ac[11 - i++] = VALID_CHARS[(int) (l1 - l * 37L)];
		}
		return new String(ac, 12 - i, i);
	}


	public static final char[] VALID_CHARS = { '_', 'a', 'b', 'c', 'd', 'e',
			'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
			's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4',
			'5', '6', '7', '8', '9' };
	
	public static final long stringToLong(String s) {
		long l = 0L;
		for (int i = 0; i < s.length() && i < 12; i++) {
			char c = s.charAt(i);
			l *= 37L;
			if (c >= 'A' && c <= 'Z')
				l += (1 + c) - 65;
			else if (c >= 'a' && c <= 'z')
				l += (1 + c) - 97;
			else if (c >= '0' && c <= '9')
				l += (27 + c) - 48;
		}
		while (l % 37L == 0L && l != 0L) {
			l /= 37L;
		}
		return l;
	}
	
	public static final int packGJString2(int position, byte[] buffer, String String) {
		int length = String.length();
		int offset = position;
		for (int index = 0; length > index; index++) {
			int character = String.charAt(index);
			if (character > 127) {
				if (character > 2047) {
					buffer[offset++] = (byte) ((character | 919275) >> 12);
					buffer[offset++] = (byte) (128 | ((character >> 6) & 63));
					buffer[offset++] = (byte) (128 | (character & 63));
				} else {
					buffer[offset++] = (byte) ((character | 12309) >> 6);
					buffer[offset++] = (byte) (128 | (character & 63));
				}
			} else
				buffer[offset++] = (byte) character;
		}
		return offset - position;
	}
	

	public static final int calculateGJString2Length(String String) {
		int length = String.length();
		int gjStringLength = 0;
		for (int index = 0; length > index; index++) {
			char c = String.charAt(index);
			if (c > '\u007f') {
				if (c <= '\u07ff')
					gjStringLength += 2;
				else
					gjStringLength += 3;
			} else
				gjStringLength++;
		}
		return gjStringLength;
	}
	
	public static final byte[] packContainer(byte[] unpackedData, int compression) {
		OutputStream stream = new OutputStream();
		stream.writeByte(compression);
		byte[] compressedData = null;
		if(compression == 0)
			compressedData = unpackedData;
		else if (compression == 1)
			compressedData = null;
		else
			compressedData = GZipCompressor.compress(unpackedData);
		stream.writeInt(compressedData.length);
		if(compression > 0)
			stream.writeInt(unpackedData.length);
		for(int index = 0; index < compressedData.length; index++)
			stream.writeByte(compressedData[index]);
		byte[] packedData = new byte[stream.getOffset()];
		stream.setOffset(0);
		stream.getBytes(packedData, 0, packedData.length);
		return packedData;
	}
	
	public static final byte[] unpackCacheContainer(byte[] packedData) {
		InputStream stream = new InputStream(packedData);
		int compression = stream.readUnsignedByte();
		int containerSize = stream.readInt();
		if (containerSize < 0 || containerSize > 5000000)
			return null;
			//throw new RuntimeException();
		if (compression == 0) {
			byte unpacked[] = new byte[containerSize];
			stream.readBytes(unpacked, 0, containerSize);
			return unpacked;
		}
		int decompressedSize = stream.readInt();
		if (decompressedSize < 0 || decompressedSize > 20000000)
			return null;
			//throw new RuntimeException();
		byte decompressedData[] = new byte[decompressedSize];
		if(compression == 1) {
			BZip2Decompressor.decompress(decompressedData, packedData, containerSize, 9);
		}else{
			GZipDecompressor.decompress(stream, decompressedData);
		}
		return decompressedData;
	}
	
	public static final int getNameHash(String name) {
		name = name.toLowerCase();
		int hash = 0;
		for (int index = 0; index < name.length(); index++)
			hash = method1258(name.charAt(index)) + ((hash << 5) - hash);
		return hash;
	}
	
	private static final byte method1258(char c) {
		byte charByte;
		if (c > 0 && c < '\200' || c >= '\240' && c <= '\377') {
			charByte = (byte) c;
		} else if (c != '\u20AC') {
			if (c != '\u201A') {
				if (c != '\u0192') {
					if (c == '\u201E') {
						charByte = -124;
					} else if (c != '\u2026') {
						if (c != '\u2020') {
							if (c == '\u2021') {
								charByte = -121;
							} else if (c == '\u02C6') {
								charByte = -120;
							} else if (c == '\u2030') {
								charByte = -119;
							} else if (c == '\u0160') {
								charByte = -118;
							} else if (c == '\u2039') {
								charByte = -117;
							} else if (c == '\u0152') {
								charByte = -116;
							} else if (c != '\u017D') {
								if (c == '\u2018') {
									charByte = -111;
								} else if (c != '\u2019') {
									if (c != '\u201C') {
										if (c == '\u201D') {
											charByte = -108;
										} else if (c != '\u2022') {
											if (c == '\u2013') {
												charByte = -106;
											} else if (c == '\u2014') {
												charByte = -105;
											} else if (c == '\u02DC') {
												charByte = -104;
											} else if (c == '\u2122') {
												charByte = -103;
											} else if (c != '\u0161') {
												if (c == '\u203A') {
													charByte = -101;
												} else if (c != '\u0153') {
													if (c == '\u017E') {
														charByte = -98;
													} else if (c != '\u0178') {
														charByte = 63;
													} else {
														charByte = -97;
													}
												} else {
													charByte = -100;
												}
											} else {
												charByte = -102;
											}
										} else {
											charByte = -107;
										}
									} else {
										charByte = -109;
									}
								} else {
									charByte = -110;
								}
							} else {
								charByte = -114;
							}
						} else {
							charByte = -122;
						}
					} else {
						charByte = -123;
					}
				} else {
					charByte = -125;
				}
			} else {
				charByte = -126;
			}
		} else {
			charByte = -128;
		}
		return charByte;
	}
	
    public static char[] aCharArray6385
	= { '\u20ac', '\0', '\u201a', '\u0192', '\u201e', '\u2026', '\u2020',
	    '\u2021', '\u02c6', '\u2030', '\u0160', '\u2039', '\u0152', '\0',
	    '\u017d', '\0', '\0', '\u2018', '\u2019', '\u201c', '\u201d',
	    '\u2022', '\u2013', '\u2014', '\u02dc', '\u2122', '\u0161',
	    '\u203a', '\u0153', '\0', '\u017e', '\u0178' };
	
    public static final String getUnformatedMessage(int messageDataLength, int messageDataOffset, byte[] messageData) {
	    char[] cs = new char[messageDataLength];
	    int i = 0;
	    for (int i_6_ = 0; i_6_ < messageDataLength; i_6_++) {
		int i_7_ = 0xff & messageData[i_6_ + messageDataOffset];
		if ((i_7_ ^ 0xffffffff) != -1) {
		    if ((i_7_ ^ 0xffffffff) <= -129
			&& (i_7_ ^ 0xffffffff) > -161) {
			int i_8_
			    = aCharArray6385[i_7_ - 128];
			if (i_8_ == 0)
			    i_8_ = 63;
			i_7_ = i_8_;
		    }
		    cs[i++] = (char) i_7_;
		}
	    }
	    return new String(cs, 0, i);
    }
	
    public static final byte[] getFormatedMessage(String message) {
	    int i_0_ = message.length();
	    byte[] is = new byte[i_0_];
	    for (int i_1_ = 0; (i_1_ ^ 0xffffffff) > (i_0_ ^ 0xffffffff);
		 i_1_++) {
		int i_2_ = message.charAt(i_1_);
		if (((i_2_ ^ 0xffffffff) >= -1 || i_2_ >= 128)
		    && (i_2_ < 160 || i_2_ > 255)) {
		    if ((i_2_ ^ 0xffffffff) != -8365) {
			if ((i_2_ ^ 0xffffffff) == -8219)
			    is[i_1_] = (byte) -126;
			else if ((i_2_ ^ 0xffffffff) == -403)
			    is[i_1_] = (byte) -125;
			else if (i_2_ == 8222)
			    is[i_1_] = (byte) -124;
			else if (i_2_ != 8230) {
			    if ((i_2_ ^ 0xffffffff) != -8225) {
				if ((i_2_ ^ 0xffffffff) != -8226) {
				    if ((i_2_ ^ 0xffffffff) == -711)
					is[i_1_] = (byte) -120;
				    else if (i_2_ == 8240)
					is[i_1_] = (byte) -119;
				    else if ((i_2_ ^ 0xffffffff) == -353)
					is[i_1_] = (byte) -118;
				    else if ((i_2_ ^ 0xffffffff) != -8250) {
					if (i_2_ == 338)
					    is[i_1_] = (byte) -116;
					else if (i_2_ == 381)
					    is[i_1_] = (byte) -114;
					else if ((i_2_ ^ 0xffffffff) == -8217)
					    is[i_1_] = (byte) -111;
					else if (i_2_ == 8217)
					    is[i_1_] = (byte) -110;
					else if (i_2_ != 8220) {
					    if (i_2_ == 8221)
						is[i_1_] = (byte) -108;
					    else if ((i_2_ ^ 0xffffffff)
						     == -8227)
						is[i_1_] = (byte) -107;
					    else if ((i_2_ ^ 0xffffffff)
						     != -8212) {
						if (i_2_ == 8212)
						    is[i_1_] = (byte) -105;
						else if ((i_2_ ^ 0xffffffff)
							 != -733) {
						    if (i_2_ != 8482) {
							if (i_2_ == 353)
							    is[i_1_]
								= (byte) -102;
							else if (i_2_
								 != 8250) {
							    if ((i_2_
								 ^ 0xffffffff)
								== -340)
								is[i_1_]
								    = (byte) -100;
							    else if (i_2_
								     != 382) {
								if (i_2_
								    == 376)
								    is[i_1_]
									= (byte) -97;
								else
								    is[i_1_]
									= (byte) 63;
							    } else
								is[i_1_]
								    = (byte) -98;
							} else
							    is[i_1_]
								= (byte) -101;
						    } else
							is[i_1_] = (byte) -103;
						} else
						    is[i_1_] = (byte) -104;
					    } else
						is[i_1_] = (byte) -106;
					} else
					    is[i_1_] = (byte) -109;
				    } else
					is[i_1_] = (byte) -117;
				} else
				    is[i_1_] = (byte) -121;
			    } else
				is[i_1_] = (byte) -122;
			} else
			    is[i_1_] = (byte) -123;
		    } else
			is[i_1_] = (byte) -128;
		} else
		    is[i_1_] = (byte) i_2_;
	    }
	    return is;
    }
    
	private Utils() {
		
	}
	
}
